<?php

// @formatter:off
/**
 * @file WCGroup.php
 * @author Alejandro Dario Simi
 * @date $Date: 2014-06-03 03:40:32 +0000 (Tue, 03 Jun 2014) $
 *
 * $Id: WCGroup.php 112 2014-06-03 03:40:32Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/includes/representations/WCGroup.php $
 */
// @formatter:on

/**
 * @class WCGroup This class represents entries saved in the table '%groups'.
 */
class WCGroup extends WCRepresentation {
	/**
	 * @var string[] This variable holds the list of columns that cannot be
	 * directly modified by the pseudo-method __set().
	 * In this case grp_id and grp_root.
	 */
	protected $_PropertiesReadOnly = array(
		"id",
		"root"
	);
	/**
	 * @var string[] This variable holds the list of columns that must be
	 * treated as booleans and then send to the database as 'Y' and 'N' by
	 * the pseudo-method __set().
	 * In this case grp_public.
	 */
	protected $_PropertiesBoolean = array(
		"hidden",
		"public"
	);
	/**
	 * @var string This is the prefix of every column on the table '%groups'.
	 */
	protected $_PropertiesPrefix = "grp_";
	/**
	 * @var string This is the name of the represented table. In this case,
	 * '%groups'.
	 */
	protected $_PropertiesTable = "groups";
	protected $_root = null;
	protected $_trash = false;
	//
	// Public methods.
	/**
	 * This method allows to add a new directory to this group.
	 *
	 * @param string $directory directory path to be added.
	 * @return boolean Returns true when the comic was successfully added.
	 */
	public function add($directory) {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Setting default value to be returned.
		$out = false;
		//
		// Checking that Read Only Mode is not activated.
		if(!$wcDefaults["read-only"]) {
			$out = true;
			//
			// Checking that directory path is not already added.
			if(!$this->has($directory)) {
				//
				// Creating a statement to add the new directory.
				// @{
				$stmt = null;
				$stmtId = __CLASS__."::".__FUNCTION__;
				if($this->_db->has($stmtId)) {
					$stmt = $this->_db->get($stmtId);
				} else {
					$query = "insert\n";
					$query .= "        into {$this->_dbprefix}directories (dir_name, dir_group)\n";
					$query .= "        values (:directory, :group)";

					$stmt = $this->_db->prepare($stmtId, $query);
				}
				// @}
				//
				// Building database parameters.
				$params = array(
					":directory" => $directory,
					":group" => $this->id
				);
				//
				// Attempting to add the directory
				if(!$stmt->execute($params)) {
					//
					// At this point, something went wrong.
					$out = false;
				}
			}
		}
		//
		// Returning addition status.
		return $out;
	}
	/**
	 * This method allows to know how many directories are associated with
	 * current group
	 *
	 * @return int Returns an amount of directories. On error it returns
	 * false.
	 */
	public function count() {
		//
		// Setting default value to be returned.
		$out = $this->count;
		//
		// Checking that current group has no issues.
		if($this->ok()) {
			//
			// If there's no count, it must be updated.
			if(!$out) {
				//
				// Creating a statement to update groups count.
				// @{
				$stmt = null;
				$stmtId = __CLASS__."::".__FUNCTION__;
				if($this->_db->has($stmtId)) {
					$stmt = $this->_db->get($stmtId);
				} else {
					$query = "select  count(1) as dir_count\n";
					$query .= "from    {$this->_dbprefix}directories\n";
					$query .= "where   dir_group = :group\n";

					$stmt = $this->_db->prepare($stmtId, $query);
				}
				// @}
				//
				// Building database parameters.
				$params = array(":group" => $this->id);
				//
				// Counting.
				if($stmt->execute($params) && $stmt->rowCount() == 1) {
					//
					// Fetching count.
					$row = $stmt->fetch();
					//
					// Saving count
					$this->count = $row["dir_count"];
					//
					// Setting return value.
					$out = $this->count;
				} else {
					//
					// Something went wrong.
					$out = false;
				}
			}
		} else {
			//
			// At this point, there's a problem with this group.
			$out = false;
		}
		//
		// Returning group's directory count.
		return $out;
	}
	/**
	 * This method allows to get a list of IDs of directories belonging to
	 * current group.
	 *
	 * @return int[] Returns a list of IDs.
	 */
	public function directories() {
		//
		// Forwarding question to directories holder.
		return array_keys(WCDirectoriesHolder::I()->itemsByGroup($this));
	}
	/**
	 * This method allows to get a list of directories belonging to current
	 * group.
	 *
	 * @return WCDirectory[] Returns a list of directories.
	 */
	public function directoriesFull() {
		//
		// Forwarding question to directories holder.
		return WCDirectoriesHolder::I()->itemsByGroup($this);
	}
	/**
	 * This method allows to know if certain directory id belongs to this
	 * group.
	 *
	 * @param int $dirId Directory ID.
	 * @return boolean Returns true when it belongs.
	 */
	public function has($dirId) {
		return in_array($dirId, $this->directories());
	}
	/**
	 * @todo doc
	 *
	 * @return boolean @todo doc
	 */
	public function isHidden() {
		return $this->hidden;
	}
	/**
	 * This method allows to know if this group is a public one.
	 *
	 * @return boolean Returns true when it's public.
	 */
	public function isPublic() {
		return $this->public;
	}
	/**
	 * This method is redefined only to disable this functionality.
	 */
	public function remove() {
		die("disabled ".__FILE__.":".__LINE__);
	}
	/**
	 * This method removes a directory from a group.
	 *
	 * @param WCDirectory $directory Directory to be removed.
	 * @return boolean Returns true when the directory is successfully removed
	 * from the current group.
	 */
	public function removeDirectory(WCDirectory &$directory) {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Setting default value to be returned.
		$out = false;
		//
		// Checking that Read Only Mode is not activated.
		if(!$wcDefaults["read-only"]) {
			if($this->has($directory->id) && $directory->name != "/") {
				//
				// Creating a statement to delete a directory from
				// the group.
				// @{
				$stmt = null;
				$stmtId = __CLASS__."::".__FUNCTION__;
				if($this->_db->has($stmtId)) {
					$stmt = $this->_db->get($stmtId);
				} else {
					$query = "delete from  {$this->_dbprefix}directories\n";
					$query .= "where        dir_id    = :directory\n";
					$query .= " and         dir_group = :group";

					$stmt = $this->_db->prepare($stmtId, $query);
				}
				// @}
				//
				// Building database parameters.
				$params = array(
					":group" => $this->id,
					":directory" => $directory->id
				);
				//
				// Removing directory.
				$out = $stmt->execute($params) && $stmt->rowCount() > 0;
			}
			//
			// When success, groups loses a directory.
			if($out) {
				$this->count--;
			}
		}
		//
		// Returning addition status.
		return $out;
	}
	/**
	 * This method allows to know current group's root directory.
	 *
	 * @return string Returns a directory full path.
	 */
	public function root() {
		return $this->root;
	}
	/**
	 * @todo doc
	 * 
	 * @return WCDirectory @todo doc
	 * 
	 */
	public function rootDirectory() {
		if($this->_root === null) {
			$dirs = WCDirectoriesHolder::I()->itemByNameInGroup("/", $this);
			$this->_root = array_shift($dirs);
			if(!$this->_root || !$this->_root->ok()) {
				$this->_root = false;
			}
		}

		return $this->_root;
	}
	/**
	 * This method allows to alter current group's public flag.
	 *
	 * @param boolean $isPublic This flag indicates the behavior this group
	 * must adopt.
	 * @return boolean Returns final status.
	 */
	public function setPublic($isPublic) {
		//
		// Setting public flag.
		$this->public = $isPublic;
		//
		// Reloading object to avoid cache problems.
		$this->reload();
		//
		// Returning final status.
		return $this->isPublic();
	}
	/**
	 * This method allows to know current group's trash directory.
	 *
	 * @return WCDirectory Returns a directory.
	 */
	public function trash() {
		if(!$this->_trash && $this->trash) {
			$dirs = WCDirectoriesHolder::I()->itemByNameInGroup($this->trash, $this);
			$this->_trash = array_shift($dirs);
			if(!$this->_trash || !$this->_trash->ok()) {
				$this->_trash = false;
			}
		}
		return $this->_trash;
	}
	//
	// Public class methods.
	/**
	 * This is a sorting method based on group id and it can be used on usort
	 * and uasort functions.
	 *
	 * @param WCGroup $a Left operand.
	 * @param WCGroup $b Right operand.
	 * @return boolean Returns true when the id of $a is greater than $b's.
	 */
	public static function IdSort(WCGroup &$a, WCGroup &$b) {
		return $a->id() > $b->id();
	}
	/**
	 * This is a sorting method based on group names and it can be used on
	 * usort and uasort functions.
	 *
	 * @param WCGroup $a Left operand.
	 * @param WCGroup $b Right operand.
	 * @return boolean Returns true when the name of $a is greater than
	 * $b's.
	 */
	public static function NameSort(WCGroup &$a, WCGroup &$b) {
		return $a->name() > $b->name();
	}
	/**
	 * This is the general sorting method and it can be used on usort and
	 * uasort functions.
	 *
	 * @param WCGroup $a Left operand.
	 * @param WCGroup $b Right operand.
	 * @return boolean Returns true when $a goes after $b.
	 */
	public static function Sort(WCGroup &$a, WCGroup &$b) {
		return self::NameSort($a, $b);
	}
}
